"""
案例：实现一个文件夹中（目录中可能还有子目录），拷贝所有的py文件，到另外一个指定的目录中。
"""
import os


# 给一个目录：D:\python_learn_code\pythonProject_01\35_list_source
# 需求：把该目录(目录下面呢还有子目录)中所有的.py文件拷贝到另外一个指定的目录中
def copy_dir(source_dir, destination_dir):
    """
    拷贝source_dir目录中所有的.py文件，到另一个目录destination_dir中
    :param source_dir:原始目录
    :param destination_dir:目标目录
    :return:返回一共拷贝的文件数量
    """
    count = 0
    for f in os.listdir(source_dir):  # 列出目录下所有的文件列表
        # 把文件名和目录拼凑成一个完整的绝对路径
        f_path = os.path.join(source_dir, f)
        if os.path.isfile(f_path) and f.endswith('.py'):  # 表示f是一个普通的py文件
            # 拷贝到指定的目录
            if not os.path.exists(destination_dir):  # 如果目标目录不存在
                os.makedirs(destination_dir)
            # 拼凑一个拷贝之后的 目标文件 的绝对路线
            sink_path = os.path.join(destination_dir, f)
            # 拷贝文件内容到sink_path
            num = copy_file(f_path, sink_path)
            count += num
        elif os.path.isdir(f_path):  # 表示 f 是一个目录
            # 采用递归函数，需要确认新的目录地址
            # 为了保持同样的目录结构，目标目录要跟着变化
            new_destination_path = os.path.join(destination_dir, f)
            copy_dir(f_path, new_destination_path)
    return count


def copy_file(source_file, sink_file):
    """
    拷贝单个文件，把source_file文件内容，拷贝到sink_file中
    :param source_file: 原始文件的绝对路径
    :param sink_file: 目标文件的绝对路径
    :return: 拷贝成功之后返回1
    """
    # 第一种写法:考虑到文件都是小文件，可以使用with语句，一次性读取全部文件内容，并一次性写入新文件
    # with open(source_file, mode='r', encoding='utf8') as source_f:
    #     content = source_f.read()
    #     with open(sink_file, mode='w', encoding='utf8') as sink_f:
    #         sink_f.write(content)

    # 第二种写法：考虑到文件都比较大，每次从源文件中读取一部分内容，并且写入到新文件中（循环多次）
    source_f = open(source_file, mode='r', encoding='utf8')
    sink_f = open(sink_file, mode='w', encoding='utf8')
    while True:
        content = source_f.read(1024 * 10)  # 每次读取10KB
        if content == '' or content is None:  # 没有读取到数据
            break  # 意味着文件读完了
        sink_f.write(content)
    source_f.close()  # 手动关闭文件
    sink_f.close()  # 手动关闭文件
    return 1


copy_dir(r'D:\python_learn_code\pythonProject_01\35_list_source', r'D:\python_learn_code\pythonProject_01\35_list_copy')
